package com.upb.webserver.config;

import com.upb.webserver.common.enums.ConfigTypeEnum;
import com.upb.webserver.common.exception.WebServerException;
import com.upb.webserver.common.pojo.base.BasePageResponse;
import com.upb.webserver.common.pojo.config.RspConfigTypeVO;
import com.upb.webserver.common.pojo.config.RspConfigVO;
import com.upb.webserver.common.returncode.ConstantCode;
import com.upb.webserver.common.tools.JsonUtils;
import com.upb.webserver.common.tools.MybatisExampleTools;
import com.upb.webserver.dao.entity.TbConfig;
import com.upb.webserver.dao.entity.TbConfigExample;
import com.upb.webserver.dao.mapper.TbConfigMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Slf4j
@Service
public class ConfigService {

    @Autowired
    private TbConfigMapper configMapper;


    /**
     * @return
     */
    public List<RspConfigTypeVO> getConfigTypeList() {
        log.info("start exec method [getConfigTypeList]");

        List<RspConfigTypeVO> rspList = new ArrayList<>();
        for (ConfigTypeEnum typeEnum : ConfigTypeEnum.values()) {
            RspConfigTypeVO rsp = new RspConfigTypeVO();
            rsp.setTypeId(typeEnum.getId());
            rsp.setTypeName(typeEnum.getName());
            rspList.add(rsp);
        }

        log.info("success exec method [getConfigTypeList],rspList:{}", JsonUtils.objToString(rspList));
        return rspList;
    }


    /**
     * @param value
     * @param typeId
     */
    public void addConfig(String value, Byte typeId) {
        log.info("start exec method [addConfig] value:{} typeId:{}", value, typeId);

        //check value and type
        TbConfigExample example = MybatisExampleTools.initSampleExample(TbConfigExample.class, new TbConfig(value, typeId));
        Optional<TbConfig> configOptional = configMapper.getOneByExample(example);
        if (configOptional.isPresent()) {
            log.warn("fail exec method [addConfig].found record by value:{} typeId:{}", value, typeId);
            throw new WebServerException(ConstantCode.CONFIG_NAME_AND_TYPE_HAD_EXIST);
        }
        //check ssh key
        if (ConfigTypeEnum.SSH_PUBLIC_KEY.getId() == typeId) {
            example = MybatisExampleTools.initSampleExample(TbConfigExample.class, new TbConfig(null, typeId));
            if (configMapper.countByExample(example) > 0) {
                log.warn("fail exec method [addConfig].found ssh-key record by typeId:{}", value, typeId);
                throw new WebServerException(ConstantCode.SSH_KEY_HAS_EXIST);
            }
        }


        //add
        TbConfig config = new TbConfig();
        config.setConfigType(typeId);
        config.setConfigName(ConfigTypeEnum.getById(typeId).getName());
        config.setConfigValue(value);
        config.setCreateTime(new Date());
        config.setModifyTime(new Date());
        configMapper.insertSelective(config);

        log.info("success exec method [addConfig] name:{} value:{} typeId:{}", value, value, typeId);

    }

    /**
     * Select config by type.
     *
     * @param type
     * @return
     */
    public BasePageResponse listConfigByType(Integer pageNumber, Integer pageSize, Byte type) {
        log.info("start exec method [listConfigByType] , pageNumber:{} pageSize:{} type:{}", pageNumber, pageSize, type);

        TbConfigExample example = MybatisExampleTools.initSamplePageExample(TbConfigExample.class, pageNumber, pageSize, new TbConfig(type));

        BasePageResponse basePageResponse = BasePageResponse.initialize();
        basePageResponse.setTotalCount(configMapper.countByExample(example));
        if (basePageResponse.getTotalCount() > 0) {
            List<TbConfig> list = configMapper.selectByExample(example);
            List<RspConfigVO> rspList = new ArrayList<>();
            for (TbConfig config : list) {
                RspConfigVO rspConfigVO = new RspConfigVO();
                rspConfigVO.setConfigId(config.getId());
                rspConfigVO.setConfigName(config.getConfigName());
                rspConfigVO.setConfigValue(config.getConfigValue());
                rspList.add(rspConfigVO);
            }
            basePageResponse.setData(list);
        }

        log.info("success exec method [listConfigByType] success, result:{}", JsonUtils.objToString(basePageResponse));
        return basePageResponse;
    }


    /**
     * @param configId
     * @return
     */
    public TbConfig verifyConfigId(int configId) {
        log.info("start exec method [verifyConfigId]. configId:{}", configId);
        TbConfig tbConfig = configMapper.selectByPrimaryKey(configId);
        if (Objects.isNull(tbConfig)) {
            log.warn("fail exec method [verifyConfigId]. not found record by configId{}", configId);
            throw new WebServerException(ConstantCode.CONFIG_ID_INVALID);
        }
        log.info("success exec method [verifyConfigId]. result:{}", JsonUtils.objToString(tbConfig));
        return tbConfig;
    }


    /**
     * @param configId
     */
    public void deleteById(int configId) {
        log.info("start exec method [deleteById] , configId:{}", configId);
        TbConfig tbConfig = verifyConfigId(configId);
        configMapper.deleteByPrimaryKey(tbConfig.getId());
        log.info("success exec method [deleteById] , configId:{}", configId);
    }
}
